package cn.texous.web.parsing.book.controller;

import cn.texous.util.commons.constant.Result;
import cn.texous.util.commons.util.StringUtils;
import cn.texous.web.parsing.book.common.constants.AnaRequesterEnum;
import cn.texous.web.parsing.book.common.constants.ContentProcessorEnum;
import cn.texous.web.parsing.book.context.AnaRequesterContext;
import cn.texous.web.parsing.book.context.ContentProcessorContext;
import cn.texous.web.parsing.book.context.OriginParserContext;
import cn.texous.web.parsing.book.feign.AnaParsingInfo;
import cn.texous.web.parsing.book.manager.UserManager;
import cn.texous.web.parsing.book.model.param.AnaSearchCatalogParam;
import cn.texous.web.parsing.book.model.param.AnaSearchChapterParam;
import cn.texous.web.parsing.book.model.param.AnaSearchFictionParam;
import cn.texous.web.parsing.book.model.parser.origin.AnaOriginParser;
import cn.texous.web.parsing.book.model.resp.AnaSearchCatalogResp;
import cn.texous.web.parsing.book.model.resp.AnaSearchChapterResp;
import cn.texous.web.parsing.book.model.resp.AnaSearchBookResp;
import cn.texous.web.parsing.book.service.api.mysql.AnaBookChapterService;
import cn.texous.web.parsing.book.service.api.mysql.AnaUserBookService;
import cn.texous.web.parsing.book.strategy.search.AnaRequester;
import cn.texous.web.parsing.book.strategy.search.ContentProcessor;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;

/**
 * 搜索接口
 * TODO 接口返回的值变为数据库中的值
 *
 * @author Showa.L
 * @since 2019/7/24 17:05
 */
@Slf4j
@RestController
@RequestMapping("/search")
@Api(value = "/search", tags = "搜索管理")
public class AnaSearchController {

    @Autowired
    private AnaRequesterContext anaRequesterContext;
    @Autowired
    private OriginParserContext originParserContext;
    @Autowired
    private ContentProcessorContext contentProcessorContext;
    @Autowired
    private AnaBookChapterService anaBookChapterService;
    @Autowired
    private AnaUserBookService anaUserBookService;

    @PostMapping("/fiction")
    @ApiOperation("书籍搜索")
    public Result<AnaSearchBookResp> fiction(@RequestBody @Valid AnaSearchFictionParam param) {
        Integer userId = UserManager.currentUserId();
        long start = System.currentTimeMillis();
        // 获取数据源解析格式
        AnaOriginParser originParser = originParserContext.loadByCode(param.getOrigin());
        // 加载请求者
        AnaRequester<AnaSearchFictionParam> anaRequester = anaRequesterContext.load(AnaRequesterEnum.FICTION);
        // 加载内容处理器
        ContentProcessor<AnaSearchBookResp> contentProcessor = contentProcessorContext.load(ContentProcessorEnum.FICTION);
        // 构建请求信息
        AnaParsingInfo info = anaRequester.getRequestInfo(param, originParser);
        // 发起请求
        Result<String> content = anaRequester.execute(info);
        // 处理内容并存储
        AnaSearchBookResp result = contentProcessor.process(content, originParser, null);
        log.info("【书籍搜索】：总耗时={}", System.currentTimeMillis() - start);
        // 返回处理结果
        return Result.ok(result);
    }

    @PostMapping("/catalog")
    @ApiOperation("目录搜索")
    public Result<AnaSearchCatalogResp> catalog(@RequestBody @Valid AnaSearchCatalogParam param) {
        Integer userId = UserManager.currentUserId();
        long start = System.currentTimeMillis();
        AnaSearchCatalogResp resp = anaBookChapterService.findCatalogRespByCache(param.getAnaBookCode());
        if (resp == null) {
            // 获取数据源
            AnaOriginParser originParser = originParserContext.loadByCode(param.getOrigin());
            // 获取请求者
            AnaRequester<AnaSearchCatalogParam> anaRequester = anaRequesterContext.load(AnaRequesterEnum.CATALOG);
            // 获取内容解析器
            ContentProcessor<AnaSearchCatalogResp> contentProcessor = contentProcessorContext.load(ContentProcessorEnum.CATALOG);
            // 生成请求信息
            AnaParsingInfo info = anaRequester.getRequestInfo(param, originParser);
            // 发起请求
            Result<String> content = anaRequester.execute(info);
            // 生成附加信息
            Map<String, Object> otherInfo = new HashMap<>();
            otherInfo.put("anaBookCode", param.getAnaBookCode());
            // 解析结果并存储
            resp = contentProcessor.process(content, originParser, otherInfo);
            log.info("【目录搜索】：总耗时={}", System.currentTimeMillis() - start);
        }
        return Result.ok(resp);
    }

    @PostMapping("/chapter")
    @ApiOperation("章节搜索")
    public Result<AnaSearchChapterResp> chapter(@RequestBody AnaSearchChapterParam param) {
        Integer userId = UserManager.currentUserId();
        long start = System.currentTimeMillis();
        AnaSearchChapterResp respT = anaBookChapterService.findByCode(param.getAnaBookChapterCode());
        AnaSearchChapterResp resp = respT;
        if (StringUtils.isTrimEmpty(resp.getContent())) {
            param.setUrl(resp.getUrl());
            // 获取数据源
            AnaOriginParser originParser = originParserContext.loadByCode(param.getOrigin());
            // 获取请求者
            AnaRequester<AnaSearchChapterParam> anaRequester = anaRequesterContext.load(AnaRequesterEnum.CHAPTER);
            // 获取内容解析器
            ContentProcessor<AnaSearchChapterResp> contentProcessor = contentProcessorContext.load(ContentProcessorEnum.CHAPTER);
            // 生成请求信息
            AnaParsingInfo info = anaRequester.getRequestInfo(param, originParser);
            // 发起请求
            Result<String> content = anaRequester.execute(info);
            // 生成附加信息
            Map<String, Object> otherInfo = new HashMap<>();
            otherInfo.put("anaBookChapterCode", param.getAnaBookChapterCode());
            // 解析结果并存储
            resp = contentProcessor.process(content, originParser, otherInfo);

            resp.setUrl(respT.getUrl());
            resp.setAnaBookCode(respT.getAnaBookCode());
            resp.setCode(respT.getCode());
            log.info("【章节搜索】：总耗时={}", System.currentTimeMillis() - start);
        }
        // TODO 存储用户阅读记录
        if (resp != null)
            anaUserBookService.insertOrUpdate(resp.getAnaBookCode(), resp.getCode(), userId);
        return Result.ok(resp);
    }

}
